//
// SdlGraph.cpp for nibbler in /home/titouan/Dropbox/Code/nibbler-epitech-2017/inc
//
// Made by creach titouan
// Login   <titouan@epitech.net>
//
// Started on  Thu Mar 13 17:09:10 2014 creach titouan
// Last update Sun Apr  6 20:54:44 2014 ledins
//

#include <iostream>
#include <cstdlib>
#include <dlfcn.h>
#include <stdexcept>
#include <ctime>
#include <algorithm>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include "exceptions.hpp"
#include "GraphGtk.hpp"

Graphics::Graphics(int argc, char **argv, int w, int h)
{
  _window = NULL;
  gtk_init(&argc, &argv);
  _h = h;
  _w = w;
  _event = IGraph::NONE;
}

void Graphics::TestLoading(GError *err, const std::string &imageName)
{
  if ( err )
    {
      throw ImageNotFoundExceptions(imageName);
    }
}

void Graphics::loadImages(const std::map<IGraph::Image, std::string> &loadMap)
{
  std::map<IGraph::Image, std::string>::const_iterator it;
  GError *err = NULL;

  for (it = loadMap.begin() ; it != loadMap.end() ; ++it)
    {
      _imgs.push_back( gdk_pixbuf_new_from_file(it->second.c_str(), &err) );
      TestLoading(err, it->second);
    }
}

void Graphics::loadFont(const std::string &)
{
}

void Graphics::writeText(char, char,char, const std::string &, int, int)
{

}

Point Graphics::getTextSize(const std::string &) const
{
  Point p;

  p.x = 0;
  p.y = 0;
  return (p);
}

void Graphics::pause()
{
  sleep(3);
}

void Graphics::clearScreen(char r, char g, char b)
{
  static int bg;
  if (GDK_IS_WINDOW(_draw->window))
    gdk_window_clear_area(_draw->window, 16, 16, _w - 32, _h - 32);

  if ( !bg )
    {
      GdkColor color;
      color.red = r;
      color.green = g;
      color.blue = b;
      gtk_widget_modify_bg(_draw, GTK_STATE_NORMAL, &color);
      bg = 42;
    }
}


void Graphics::button_clicked_call_back(GtkWidget *widget, GdkEventKey *event, gpointer *data)
{
  reinterpret_cast<Graphics*>(data)->on_key_press(widget, event, *data);
}

void Graphics::delete_event(gpointer *data)
{
  reinterpret_cast<Graphics*>(data)->_event = IGraph::QUIT;
}

IGraph::Event Graphics::on_key_press (GtkWidget *, GdkEventKey *event, gpointer)
{
  switch ( event->keyval )
    {
    case GDK_Left:
      _event = IGraph::LEFT;
      return IGraph::LEFT;
      break;
    case GDK_Right:
      _event = IGraph::RIGHT;
      return IGraph::RIGHT;
      break;
    case GDK_Up:
      _event = IGraph::UP;
      return IGraph::UP;
      break;
    case GDK_Down:
      _event = IGraph::DOWN;
      return IGraph::DOWN;
      break;
    case GDK_Escape:
      _event = IGraph::QUIT;
      return IGraph::QUIT;
      break;

    }
  _event = IGraph::NONE;
  return (IGraph::NONE);
}

void Graphics::openWindow()
{
  _window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(_window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(_window), _w, _h);
  gtk_window_set_title(GTK_WINDOW(_window), "Nibbler [Gtk]");
  g_signal_connect (G_OBJECT (_window), "key_press_event",
                    G_CALLBACK (Graphics::button_clicked_call_back), this);
  _draw = gtk_drawing_area_new();
  gtk_container_add (GTK_CONTAINER(_window), _draw);
  g_signal_connect(G_OBJECT (_draw), "delete-event", G_CALLBACK (Graphics::delete_event), this);
}

void Graphics::display()
{
  if (GTK_IS_WIDGET(_window))
    gtk_widget_show_all(_window);
  gtk_main_iteration_do(FALSE);
}

void Graphics::drawBlock(IGraph::Image img, int x, int y)
{
  if (GDK_IS_DRAWABLE(_draw->window) == TRUE)
    gdk_draw_pixbuf(_draw->window, NULL, _imgs[img], 0, 0, x, y, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0);
}

void Graphics::wait(unsigned int d) const
{
  usleep(d * 800);
}

Graphics::~Graphics()
{
  GList *children, *iter;

  children = gtk_container_get_children(GTK_CONTAINER(_window));
  for(iter = children; iter != NULL; iter = g_list_next(iter))
    gtk_widget_destroy(GTK_WIDGET(iter->data));
  g_list_free(children);

  for_each(_imgs.begin(), _imgs.end(), g_object_unref);
}


IGraph::Event Graphics::getNextEvent()
{
  IGraph::Event tmp;

  tmp = _event;
  _event = IGraph::NONE;
  return (tmp);
}

unsigned int Graphics::getCurrentTime() const
{
  unsigned int sysTime;
  unsigned int sysTimeMS;

  sysTime = time(0);
  sysTimeMS = sysTime*1000;
  return (sysTimeMS);
}
